home *** CD-ROM | disk | FTP | other *** search
- /* Low level AX.25 frame processing - address header */
-
- #include <stdio.h>
- #include "global.h"
- #include "mbuf.h"
- #include "iface.h"
- #include "timer.h"
- #include "arp.h"
- #include "slip.h"
- #include "ax25.h"
- #include "lapb.h"
- #include <ctype.h>
-
- /* AX.25 broadcast address: "QST-0" in shifted ascii */
- struct ax25_addr ax25_bdcst = {
- 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1,
- ('0'<<1) | E,
- };
- char axbdcst[AXALEN]; /* Same thing, network format */
- struct ax25_addr mycall;
- int digipeat = 1; /* Controls digipeating */
-
- int digisent = 0; /* DG2KK: counts frames to be digipeated */
- /* Send IP datagrams across an AX.25 link */
- int
- ax_send(bp,interface,gateway,precedence,delay,throughput,reliability)
- struct mbuf *bp;
- struct interface *interface;
- int32 gateway;
- char precedence;
- char delay;
- char throughput;
- char reliability;
- {
- char *hw_addr,*res_arp();
- struct ax25_cb *axp,*find_ax25(),*open_ax25();
- struct ax25 addr;
- struct ax25_addr destaddr;
- struct mbuf *tbp;
- extern int16 axwindow;
- void ax_incom();
- int16 size,bsize,seq;
-
- if((hw_addr = res_arp(interface,ARP_AX25,gateway,bp)) == NULLCHAR)
- return; /* Wait for address resolution */
-
- if(delay || (!reliability && (interface->flags == DATAGRAM_MODE))){
- /* Use UI frame */
- (*interface->output)(interface,hw_addr,
- interface->hwaddr,PID_FIRST|PID_LAST|PID_IP,bp);
- return;
- }
- /* Reliability is needed; use I-frames in AX.25 connection */
- memcpy(destaddr.call,hw_addr,ALEN);
- destaddr.ssid = hw_addr[ALEN];
-
- if((axp = find_ax25(&destaddr)) == NULLAX25 || axp->state != CONNECTED){
- /* Open a new connection or reinitialize the old one */
- atohax25(&addr,hw_addr,(struct ax25_addr *)interface->hwaddr);
- axp = open_ax25(&addr,axwindow,ax_incom,NULLVFP,NULLVFP,interface,(char *)0);
- if(axp == NULLAX25){
- free_p(bp);
- return;
- }
- }
- /* If datagram is too big for one frame, send all but the last with
- * the extension PID. Note: the copy to a new buf is necessary because
- * AX.25 may continue retransmitting the frame after a local TCB has
- * gone away, and using the buf directly would cause heap garbage to be
- * transmitted. Besides, nobody would ever use AX.25 anywhere
- * high performance is needed anyway...
- */
- bsize = len_mbuf(bp);
- seq = 0;
- while(bsize != 0){
- size = min(bsize,axp->paclen);
- /* Allocate buffer, allowing space for PID */
- if((tbp = alloc_mbuf(size + 1)) == NULLBUF)
- break; /* out of memory! */
- *tbp->data = PID_IP;
- if(seq++ == 0)
- *tbp->data |= PID_FIRST; /* First in sequence */
- if(size == bsize)
- *tbp->data |= PID_LAST; /* That's all of it */
- /* else more to follow */
-
- tbp->cnt = 1;
- tbp->cnt += pullup(&bp,tbp->data + 1,size);
- send_ax25(axp,tbp);
- bsize -= size;
- }
- free_p(bp); /* Shouldn't be necessary */
- }
- /* Add AX.25 link header and send packet.
- * Note that the calling order here must match ec_output
- * since ARP also uses it.
- */
- ax_output(interface,dest,source,pid,bp)
- struct interface *interface;
- char *dest; /* Destination AX.25 address (7 bytes, shifted) */
- /* Also includes digipeater string */
- char *source; /* Source AX.25 address (7 bytes, shifted) */
- char pid; /* Protocol ID */
- struct mbuf *bp; /* Data field (follows PID) */
- {
- struct mbuf *abp,*cbp,*htonax25();
- struct ax25 addr;
-
- atohax25(&addr,dest,(struct ax25_addr *)source);
- if((abp = htonax25(&addr)) == NULLBUF){
- free_p(bp);
- return;
- }
- /* Allocate mbuf for control and PID fields, and fill in */
- if((cbp = alloc_mbuf((int16)2)) == NULLBUF){
- free_p(abp);
- free_p(bp);
- return;
- }
- cbp->data[0] = UI;
- cbp->data[1] = pid;
- cbp->cnt = 2;
-
- /* Link everything together and ship it */
- abp->next = cbp;
- cbp->next = bp;
- (*interface->raw)(interface,abp);
- }
- /* Process incoming AX.25 packets.
- * After optional tracing, the address field is examined. If it is
- * directed to us as a digipeater, repeat it. If it is addressed to
- * us or to QST-0, kick it upstairs depending on the protocol ID.
- */
- int
- ax_recv(interface,bp)
- struct interface *interface;
- struct mbuf *bp;
- {
- void ip_route(),arp_input();
- struct ax25_addr *ap;
- struct mbuf *htonax25(),*hbp;
- char multicast = 0;
- char nrnodes = 0; /* DG2KK */
- char control;
- struct ax25 hdr;
- struct ax25_cb *axp,*find_ax25(),*cr_ax25();
- struct ax25_addr ifcall;
- extern struct ax25_addr nr_nodebc;
-
- /* we need to use the call for this interface */
- memcpy(ifcall.call,interface->hwaddr,ALEN);
- ifcall.ssid = interface->hwaddr[ALEN];
-
- /* Pull header off packet and convert to host structure */
- if(ntohax25(&hdr,&bp) < 0){
- /* Something wrong with the header */
- free_p(bp);
- return;
- }
- /* Scan, looking for our call in the repeater fields, if any.
- * Repeat appropriate packets.
- */
- for(ap = &hdr.digis[0]; ap < &hdr.digis[hdr.ndigis]; ap++){
- if(ap->ssid & REPEATED)
- continue; /* Already repeated */
- /* Count frames to be digipeated, even if digipeat is off
- * (DG2KK)
- */
- if (addreq(ap,&mycall))
- digisent++;
- /* Check if packet is directed to us as a digipeater */
- if(digipeat && addreq(ap,&mycall)){
- /* Yes, kick it back out */
- ap->ssid |= REPEATED;
- if((hbp = htonax25(&hdr)) != NULLBUF){
- hbp->next = bp;
- if(interface->forw != NULLIF)
- (*interface->forw->raw)(interface->forw,hbp);
- else
- (*interface->raw)(interface,hbp);
- bp = NULLBUF;
- }
- }
- free_p(bp); /* Dispose if not forwarded */
- return;
- }
- /* Packet has passed all repeaters, now look at destination */
- if(addreq(&hdr.dest,&ax25_bdcst)){
- multicast = 1; /* Broadcast packet */
- } else if(addreq(&hdr.dest,&mycall)){ /* DG2KK: was: &ifcall */
- multicast = 0; /* Packet directed at us */
- } else if(addreq(&hdr.dest,&nr_nodebc)) {
- nrnodes = 1;
- } else {
- /* Not for us */
- free_p(bp);
- return;
- }
- if(bp == NULLBUF){
- /* Nothing left */
- return;
- }
- /* Sneak a peek at the control field. This kludge is necessary because
- * AX.25 lacks a proper protocol ID field between the address and LAPB
- * sublayers; a control value of UI indicates that LAPB is to be
- * bypassed.
- */
- control = *bp->data & ~PF;
- if(control == UI){
- char pid;
-
- (void) pullchar(&bp);
- if(pullup(&bp,&pid,1) != 1)
- return; /* No PID */
- /* DG2KK: new from netrom version */
- if (nrnodes) {
- if ((pid & (PID_FIRST | PID_LAST | PID_PID)) ==
- (PID_NETROM | PID_FIRST | PID_LAST))
- nr_nodercv(interface,&hdr.source,bp);
- else /* regular UI packets to "nodes" aren't for us */
- free_p(bp);
- return;
- }
- else {
- /* Handle packets. Multi-frame messages are not allowed */
- switch(pid & (PID_FIRST | PID_LAST | PID_PID)){
- case (PID_IP | PID_FIRST | PID_LAST):
- ip_route(bp,multicast);
- break;
- case (PID_ARP | PID_FIRST | PID_LAST):
- arp_input(interface,bp);
- break;
- default:
- free_p(bp);
- break;
- }
- return;
- }
- }
-
- /* If the packet was an I packet not directed to us,
- * we should drop it here (shouldn't we, Phil?)
- */
- if (nrnodes || multicast) {
- free_p(bp);
- return;
- }
-
- /* Find the source address in hash table */
- if((axp = find_ax25(&hdr.source)) == NULLAX25){
- /* Create a new ax25 entry for this guy,
- * insert into hash table keyed on his address,
- * and initialize table entries
- */
- if((axp = cr_ax25(&hdr.source)) == NULLAX25){
- free_p(bp);
- return;
- }
- axp->interface = interface;
- /* Swap source and destination, reverse digi string */
- ASSIGN(axp->addr.dest,hdr.source);
- ASSIGN(axp->addr.source,hdr.dest);
- if(hdr.ndigis > 0){
- int i,j;
-
- /* Construct reverse digipeater path */
- for(i=hdr.ndigis-1,j=0;i >= 0;i--,j++){
- ASSIGN(axp->addr.digis[j],hdr.digis[i]);
- axp->addr.digis[j].ssid &= ~(E|REPEATED);
- }
- /* Scale timers to account for extra delay */
- axp->t1.start *= hdr.ndigis+1;
- axp->t2.start *= hdr.ndigis+1;
- axp->t3.start *= hdr.ndigis+1;
- }
- axp->addr.ndigis = hdr.ndigis;
- }
- if(hdr.cmdrsp == UNKNOWN)
- axp->proto = V1; /* Old protocol in use */
- else
- axp->proto = V2;
-
- lapb_input(axp,hdr.cmdrsp,bp);
- }
-
- /* General purpose AX.25 frame output */
- sendframe(axp,cmdrsp,ctl,bp)
- struct ax25_cb *axp;
- char cmdrsp;
- char ctl;
- struct mbuf *bp;
- {
- struct mbuf *hbp,*cbp,*htonax25();
-
- if(axp == NULL){
- printf("NULL AXP!!\n");
- return;
- }
- if(axp->interface == NULLIF){
- printf("NULL IF PTR!!\n");
- return;
- }
- axp->addr.cmdrsp = cmdrsp;
- /* Create address header */
- hbp = htonax25(&axp->addr);
-
- /* Add control field */
- if((cbp = alloc_mbuf(1)) == NULLBUF){
- free_p(bp);
- free_p(hbp);
- return;
- }
- *cbp->data = ctl;
- cbp->cnt = 1;
-
- /* Link together and send */
- cbp->next = bp;
- hbp->next = cbp;
- if(axp->interface->raw != NULL)
- (*axp->interface->raw)(axp->interface,hbp);
- else {
- printf("NULL RAW POINTER!!\n");
- fflush(stdout);
- }
- if(cmdrsp == COMMAND)
- start_timer(&axp->t1);
- }
- /* Initialize AX.25 entry in arp device table */
- axarp()
- {
- int psax25(),setpath();
-
- memcpy(axbdcst,ax25_bdcst.call,ALEN);
- axbdcst[ALEN] = ax25_bdcst.ssid;
-
- arp_init(ARP_AX25,AXALEN,PID_FIRST|PID_LAST|PID_IP,
- PID_FIRST|PID_LAST|PID_ARP,axbdcst,psax25,setpath);
- }
-